﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI.WebControls;
using BE;

namespace VentaPorCatalogos.Models
{
    public class DivisionesTreeView : TreeView
    {
        /// <summary>
        /// Returns a new instance of the TreeNode class. 
        /// The CreateNode is a helper method.
        /// </summary>
        protected override TreeNode CreateNode()
        {
            return new DivisionNode(this, false);
            
        }       
        
    }

    public enum TipoNodo
    {
        Raiz = 0,
        Division,
        Zona,
        Area
    }

    public enum AccionNodo
    {
        Ninguna = 0,
        Crear,
        Editar,
        Eliminar
    }

    public class DivisionNode : TreeNode 
    {
        public TipoNodo TipoNodo { get; set; }
        public BaseBE Elemento { get; private set; }
        public List<DivisionBE> Divisiones { get; set; }
        public AccionNodo AccionNodo { get; set; }

        public T GetElemento<T>() where T : BaseBE
        {
            switch (this.TipoNodo)
            {
                case Models.TipoNodo.Division:
                    if (typeof(T) != typeof(DivisionBE))
                        throw new Exception("Tipo inesperado en TreeView. Se espera DivisionBE");
                    break;
                case Models.TipoNodo.Zona:
                    if (typeof(T) != typeof(ZonasBE))
                        throw new Exception("Tipo inesperado en TreeView. Se espera ZonasBE");
                    break;
                case Models.TipoNodo.Area:
                    if (typeof(T) != typeof(AreaBE))
                        throw new Exception("Tipo inesperado en TreeView. Se espera AreaBE");
                    break;
            }
            return (T)Elemento;            
        }

        public DivisionNode() : base()
        {
        }

        public DivisionNode(TreeView pTreeView, bool isRoot) : base(pTreeView, isRoot)
        {
        }
        public DivisionNode(List<DivisionBE> pDivisiones)
        {
            this.Text = "Divisiones";
            this.Value = "";
            this.TipoNodo = Models.TipoNodo.Raiz;
            this.SelectAction = TreeNodeSelectAction.Select;
            this.Divisiones = pDivisiones;
            SetearImagenNodo();
            PopulateNodes();
        }

        public DivisionNode(BaseBE pElemento)
        {
            this.Elemento = pElemento;

            if (pElemento is DivisionBE)
            {
                this.Text = (pElemento as DivisionBE).Descripcion;
                this.Value = (pElemento as DivisionBE).IdDivision.ToString();
                this.TipoNodo = Models.TipoNodo.Division;
                this.SelectAction = TreeNodeSelectAction.SelectExpand;                
                this.PopulateOnDemand = true;
                PopulateNodes();

            }
            else
                if (pElemento is ZonasBE)
                {
                    this.Text = (pElemento as ZonasBE).Descripcion;
                    this.Value = (pElemento as ZonasBE).IdZona.ToString();
                    this.TipoNodo = Models.TipoNodo.Zona;
                    this.SelectAction = TreeNodeSelectAction.SelectExpand;
                    this.PopulateOnDemand = true;                    
                    PopulateNodes();
                }
                else
                    if (pElemento is AreaBE)
                    {
                        this.Text = (pElemento as AreaBE).Descripcion;
                        this.Value = (pElemento as AreaBE).IdArea.ToString();
                        this.TipoNodo = Models.TipoNodo.Area;
                        this.SelectAction = TreeNodeSelectAction.Select;                        
                    }
            SetearImagenNodo();            
        }

        public void AgregarNodo(string pDescripcion, int? pIdVendedorGteZonal, string pGerenteZonal)
        {
            DivisionNode oNewNode = null;
            switch (this.TipoNodo)
            {
                case Models.TipoNodo.Raiz:
                    DivisionBE oDivisionBE = new DivisionBE() { Descripcion = pDescripcion };
                    Divisiones.Add(oDivisionBE);
                    oNewNode = new DivisionNode(oDivisionBE);
                    oNewNode.PopulateOnDemand = false;
                    break;

                case Models.TipoNodo.Division:
                    ZonasBE oZonaBE = new ZonasBE() { Descripcion = pDescripcion, 
                                                      IdVendedorGteZonal = pIdVendedorGteZonal,
                                                      GerenteZonal = pGerenteZonal };
                    (this.Elemento as DivisionBE).Zonas.Add(oZonaBE);
                    oNewNode = new DivisionNode(oZonaBE);
                    oNewNode.PopulateOnDemand = false;
                    break;
                case Models.TipoNodo.Zona:
                    AreaBE oAreaBE = new AreaBE() { Descripcion = pDescripcion };
                    (this.Elemento as ZonasBE).Areas.Add(oAreaBE);
                    oNewNode = new DivisionNode(oAreaBE);                                                     
                    break;
                case Models.TipoNodo.Area:
                    return;
            }
            oNewNode.AccionNodo = Models.AccionNodo.Crear;
            this.ChildNodes.Add(oNewNode);
            oNewNode.Selected = true;            
        }

        public void EditarNodo(string pDescripcion, int? pIdVendedorGteZonal, string pGerenteZonal)
        {
            switch (this.TipoNodo)
            {
                case Models.TipoNodo.Raiz:             
                    return;
                    
                case Models.TipoNodo.Division:
                    (this.Elemento as DivisionBE).Descripcion = pDescripcion;
                    this.Text = pDescripcion;                    
                    break;
                case Models.TipoNodo.Zona:
                    (this.Elemento as ZonasBE).Descripcion = pDescripcion;
                    (this.Elemento as ZonasBE).IdVendedorGteZonal = pIdVendedorGteZonal;
                    (this.Elemento as ZonasBE).GerenteZonal = pGerenteZonal;
                    this.Text = pDescripcion;
                    break;
                case Models.TipoNodo.Area:                    
                    (this.Elemento as AreaBE).Descripcion = pDescripcion;
                    this.Text = pDescripcion;
                    break;
            }
            if (this.AccionNodo == Models.AccionNodo.Eliminar)
                SetearImagenNodo();
            if (this.AccionNodo != Models.AccionNodo.Crear)
                this.AccionNodo = Models.AccionNodo.Editar;
            
        }

        private void SetearImagenNodo()
        {
            switch (this.TipoNodo)
            {
                case Models.TipoNodo.Raiz:
                    this.ImageUrl = "~/images/global.png";                    
                    return;
                case Models.TipoNodo.Division:
                    this.ImageUrl = "~/images/division.png";                    
                    break;
                case Models.TipoNodo.Zona:
                    this.ImageUrl = "~/images/zona.png";
                    break;
                case Models.TipoNodo.Area:
                    this.ImageUrl = "~/images/area.png";                    
                    break;
            }
        }

        public void QuitarNodo()
        {
            switch (this.TipoNodo)
            {
                case Models.TipoNodo.Raiz:
                    return;

                case Models.TipoNodo.Division:
                case Models.TipoNodo.Zona:
                case Models.TipoNodo.Area:
                    if (this.AccionNodo != Models.AccionNodo.Crear)
                    {
                        this.ImageUrl = this.ImageUrl = "~/images/pendingdelete.png";
                        this.AccionNodo = Models.AccionNodo.Eliminar;
                    }
                    else
                    {
                        TreeNode oNodoPadre = this.Parent;
                        if (oNodoPadre != null)
                            oNodoPadre.ChildNodes.Remove(this);    
                    }
                break;
            }            
        }
        protected override object SaveViewState()
        {
            object[] arrState = new object[5];
            arrState[0] = this.Elemento;
            arrState[1] = this.TipoNodo;
            arrState[2] = this.AccionNodo;
            arrState[3] = this.Divisiones;
            arrState[4] = base.SaveViewState();

            return arrState;
        }

        protected override void LoadViewState(object state)
        {
            object[] arrState = state as object[];
            if (arrState[0] != null)
                this.Elemento = (BaseBE)arrState[0];
            this.TipoNodo = (Models.TipoNodo)arrState[1];
            this.AccionNodo = (Models.AccionNodo)arrState[2];
            this.Divisiones = (List<DivisionBE>)arrState[3];
            base.LoadViewState(arrState[4]);
        }

        public void PopulateNodes()
        {
            switch (this.TipoNodo)
            {
                case Models.TipoNodo.Raiz:
                    this.Divisiones.ForEach(x => this.ChildNodes.Add(new DivisionNode(x)));
                    break;
                case Models.TipoNodo.Division:
                    (this.Elemento as DivisionBE).Zonas.ForEach(x => this.ChildNodes.Add(new DivisionNode(x)));
                    break;
                case Models.TipoNodo.Zona:
                    (this.Elemento as ZonasBE).Areas.ForEach(x => this.ChildNodes.Add(new DivisionNode(x)));
                    break;
                case Models.TipoNodo.Area:                    
                    break;
            }                        
        }

    }


    public class DivisionesModel
    {
        public DivisionNode NodoASeleccionar { get; set; }
    }
}